#Responsability:
#Execute de model ldndc and return the output

#Load Needs
#Configuration object

Model <- setRefClass(    
  "model"
  , fields = list(
      projectPath="character",
      projectFile="character",
      modelPath="character",
      outputFile="character",
      outputColumn="character",
      outputConversion="numeric",
      parameterFile="character"      
  )
  , methods = list(
    #
    #
    # Constructor
    #
    #
    initialize = function(projectPath="",
                          projectFile=configuration@projectFile,
                          modelPath=configuration@commonFolder,
                          outputFile=configuration@outputFile,
                          outputColumn=configuration@outputColumn,
                          outputConversion=configuration@outputConversion,
                          parameterFile=configuration@parameterFile, 
                          ...)
    {
      
      callSuper(..., 
                projectPath=projectPath,
                projectFile=projectFile,
                modelPath=modelPath,
                outputFile=outputFile,
                outputColumn=outputColumn,
                outputConversion=outputConversion,
                parameterFile=parameterFile)
    },
    #
    #
    # Delete the output file if it already exists
    #
    #
    removeOutputFile = function() {
      
      logdebug("METHOD IN: removeOutputFile")
      
      outputPath <- paste(modelPath, projectPath, outputFile, sep="")
      
      status  <- system(paste("rm -rf ", outputPath))
      
      logdebug("METHOD OUT: removeOutputFile")
      
      status
    },
    #
    #
    # Execute the model
    # Input: data.frame with the parameters
    #
    #
    executeModel = function(parameters) {
      
      logdebug("METHOD IN: executeModel")
      
      modifyParametersFile(parameters)
      
      cmd <- paste(modelPath, "./ldndc -c ", modelPath, "ldndc.conf ", paste(modelPath, projectPath, projectFile, sep=""),  sep="")
    
      loginfo(cmd)
      system(cmd,intern=TRUE)
      
      #Configurar el ldndc para que la salida por consola sea la esperada y no necesitar esta lectura de disco
      output <- NULL
      
      tryCatch( {
        output <- readOutput()
      },
      error= function(err) {
        logerror(err)
        logerror("Error reading model output.")
      })
            
      logdebug("METHOD OUT: executeModel")
      
      output
    },
    #
    #
    # Modify the file that the model use for its execution
    # Input: data.frame with the new parameters
    #
    modifyParametersFile = function(parameters) {
      
      logdebug("METHOD IN: modifyLdndcParameters")
      
      if (!is.data.frame(parameters))
        stop("The parameters should be stored is a data.frame")
      
      fileName <- paste(modelPath,projectPath,parameterFile,sep="")
      
      fileConn<-file(fileName)
      writeLines(c('','%siteparameters','id = "0"','','%data'), fileConn)
      close(fileConn)
      
      write.table(parameters,fileName,sep="=",dec=".",col.names=F,quote=F,append=TRUE)
   
      logdebug("METHOD OUT: modifyLdndcParameters")
      
    },
    
    #
    #
    #Read the configured output file of the ldndc model
    #Return: the output of the model
    #
    #
    readOutput = function()
    {
      logdebug("METHOD IN: readOutput")
      
      output <- read.table(paste(modelPath, projectPath, outputFile, sep=""),header=T,dec=".",sep="\t")
      
      #TODO output <- outputParser(output)
      
      logdebug("METHOD OUT: readOutput")
      
      output
    },
    #
    #
    #If the output has the important column divided in more than one we add all together
    #
    #
    outputParser = function(output) {
        
      logdebug("SUBMETHOD IN: outputParser")
      
      outputParsed <- 0
      
      for ( col in outputColumn)
      {
        # adding output 
        outputParsed <- outputParsed +  output[, col ]
      }
      
      outputParsed <- outputParsed * outputConversion
      
      if (sum(is.na(outputParsed)) > 0) {
        stop("NA's found in Output, maybe not all Values are calculated (e.g. leap year)")
      }
      
      logdebug("SUBMETHOD OUT: outputParser")
      
      outputParsed
    }
    
    
    
  )#End methods List 
  
)#End RefClass
